from typing import Optional, List, Tuple, Dict, Any
from app.modules.system.models import SystemConfigModel
from app.modules.system.schemas import SystemConfigCreate, SystemConfigUpdate
from app.core.exceptions import BusinessException, NotFoundException
from tortoise.exceptions import IntegrityError
import json


class SystemConfigService:
    """系统配置服务类"""
    
    @staticmethod
    async def create_config(config_in: SystemConfigCreate) -> SystemConfigModel:
        """创建系统配置"""
        try:
            # 检查配置键是否已存在
            existing_config = await SystemConfigModel.get_or_none(key=config_in.key)
            if existing_config:
                raise BusinessException(message="配置键已存在")
            
            # 验证配置值格式
            await SystemConfigService._validate_config_value(config_in.value, config_in.type)
            
            # 创建配置
            config = await SystemConfigModel.create(**config_in.dict())
            return config
        except IntegrityError:
            raise BusinessException(message="配置键已存在")
        except Exception as e:
            raise BusinessException(message=f"创建配置失败: {str(e)}")

    @staticmethod
    async def get_config_by_id(config_id: int) -> SystemConfigModel:
        """根据ID获取配置"""
        config = await SystemConfigModel.get_or_none(id=config_id)
        if not config:
            raise NotFoundException(message="配置不存在")
        return config

    @staticmethod
    async def get_config_by_key(key: str) -> Optional[SystemConfigModel]:
        """根据键获取配置"""
        return await SystemConfigModel.get_or_none(key=key)

    @staticmethod
    async def update_config(config_id: int, config_in: SystemConfigUpdate) -> SystemConfigModel:
        """更新系统配置"""
        config = await SystemConfigService.get_config_by_id(config_id)
        
        # 更新字段
        update_data = config_in.dict(exclude_unset=True)
        
        # 如果更新了值，需要验证格式
        if "value" in update_data and "type" in update_data:
            await SystemConfigService._validate_config_value(update_data["value"], update_data["type"])
        elif "value" in update_data:
            await SystemConfigService._validate_config_value(update_data["value"], config.type)
        
        # 更新配置
        await config.update_from_dict(update_data).save()
        return config

    @staticmethod
    async def delete_config(config_id: int) -> None:
        """删除系统配置"""
        config = await SystemConfigService.get_config_by_id(config_id)
        
        # 系统配置不允许删除
        if config.is_system:
            raise BusinessException(message="系统配置不允许删除")
        
        await config.delete()

    @staticmethod
    async def get_config_list(
        skip: int = 0,
        limit: int = 10,
        key: Optional[str] = None,
        type: Optional[str] = None,
        is_system: Optional[bool] = None,
        is_public: Optional[bool] = None
    ) -> Tuple[int, List[SystemConfigModel]]:
        """获取配置列表"""
        # 构建查询条件
        query = SystemConfigModel.all()
        
        if key:
            query = query.filter(key__icontains=key)
        if type:
            query = query.filter(type=type)
        if is_system is not None:
            query = query.filter(is_system=is_system)
        if is_public is not None:
            query = query.filter(is_public=is_public)
        
        # 获取总数和列表
        total = await query.count()
        configs = await query.offset(skip).limit(limit).order_by('key')
        
        return total, configs

    @staticmethod
    async def batch_update_configs(configs: List[Dict[str, Any]]) -> List[SystemConfigModel]:
        """批量更新配置"""
        updated_configs = []
        
        for config_data in configs:
            if 'key' not in config_data or 'value' not in config_data:
                continue
            
            key = config_data['key']
            value = config_data['value']
            
            # 获取现有配置
            config = await SystemConfigModel.get_or_none(key=key)
            if config:
                # 验证值格式
                await SystemConfigService._validate_config_value(value, config.type)
                # 更新配置
                config.value = value
                await config.save()
                updated_configs.append(config)
            else:
                # 创建新配置
                new_config = await SystemConfigModel.create(
                    key=key,
                    value=value,
                    type="string",
                    description=f"自动创建的配置: {key}"
                )
                updated_configs.append(new_config)
        
        return updated_configs

    @staticmethod
    async def get_public_configs() -> List[SystemConfigModel]:
        """获取公开配置"""
        return await SystemConfigModel.filter(is_public=True).order_by('key')

    @staticmethod
    async def get_system_configs() -> List[SystemConfigModel]:
        """获取系统配置"""
        return await SystemConfigModel.filter(is_system=True).order_by('key')

    @staticmethod
    async def get_config_value(key: str, default: Any = None) -> Any:
        """获取配置值（带类型转换）"""
        config = await SystemConfigModel.get_or_none(key=key)
        if not config:
            return default
        
        return SystemConfigService._convert_value(config.value, config.type)

    @staticmethod
    async def set_config_value(
        key: str,
        value: Any,
        description: str = None,
        config_type: str = "string",
        is_system: bool = False,
        is_public: bool = True
    ) -> SystemConfigModel:
        """设置配置值"""
        # 转换为字符串
        if isinstance(value, (dict, list)):
            value = json.dumps(value, ensure_ascii=False)
        else:
            value = str(value)
        
        # 验证值格式
        await SystemConfigService._validate_config_value(value, config_type)
        
        # 获取或创建配置
        config, created = await SystemConfigModel.get_or_create(
            key=key,
            defaults={
                "value": value,
                "description": description,
                "type": config_type,
                "is_system": is_system,
                "is_public": is_public
            }
        )
        
        if not created:
            config.value = value
            config.description = description
            config.type = config_type
            config.is_system = is_system
            config.is_public = is_public
            await config.save()
        
        return config

    @staticmethod
    async def _validate_config_value(value: str, config_type: str) -> None:
        """验证配置值格式"""
        try:
            if config_type == "int":
                int(value)
            elif config_type == "float":
                float(value)
            elif config_type == "bool":
                if value.lower() not in ["true", "false", "1", "0", "yes", "no"]:
                    raise ValueError("布尔值格式错误")
            elif config_type == "json":
                json.loads(value)
            # string类型不需要验证
        except (ValueError, json.JSONDecodeError) as e:
            raise BusinessException(message=f"配置值格式错误: {str(e)}")

    @staticmethod
    def _convert_value(value: str, config_type: str) -> Any:
        """转换配置值类型"""
        try:
            if config_type == "int":
                return int(value)
            elif config_type == "float":
                return float(value)
            elif config_type == "bool":
                return value.lower() in ["true", "1", "yes"]
            elif config_type == "json":
                return json.loads(value)
            else:
                return value
        except (ValueError, json.JSONDecodeError):
            return value

    @staticmethod
    async def export_configs(
        keys: Optional[List[str]] = None,
        include_system: bool = True,
        include_private: bool = False
    ) -> List[Dict[str, Any]]:
        """导出配置"""
        query = SystemConfigModel.all()
        
        if keys:
            query = query.filter(key__in=keys)
        if not include_system:
            query = query.filter(is_system=False)
        if not include_private:
            query = query.filter(is_public=True)
        
        configs = await query.order_by('key')
        
        return [
            {
                "key": config.key,
                "value": config.value,
                "description": config.description,
                "type": config.type,
                "is_system": config.is_system,
                "is_public": config.is_public,
                "remark": config.remark
            }
            for config in configs
        ]

    @staticmethod
    async def import_configs(configs: List[Dict[str, Any]]) -> List[SystemConfigModel]:
        """导入配置"""
        imported_configs = []
        
        for config_data in configs:
            try:
                config = await SystemConfigService.set_config_value(
                    key=config_data["key"],
                    value=config_data["value"],
                    description=config_data.get("description"),
                    config_type=config_data.get("type", "string"),
                    is_system=config_data.get("is_system", False),
                    is_public=config_data.get("is_public", True)
                )
                imported_configs.append(config)
            except Exception as e:
                print(f"导入配置失败 {config_data.get('key')}: {str(e)}")
        
        return imported_configs 